<?php
namespace App\Http\Services;

use Exception;
use Illuminate\Support\Facades\DB;
use App\Lib\Bls;
use App\Lib\Yuque;
use App\Lib\Alipay;
use App\Http\Model\Hint;
use App\Http\Model\FinanceWithdrawOrder;
use App\Http\Model\UserVerify;
use App\Http\Model\FinanceKk;
use App\Http\Model\FinanceNotifyLog;

class FinanceWithdrawNewServices extends CommonServices
{
    protected $blsLib;
    protected $yuqueLib;
    protected $alipayLib;
    protected $withdrawOrderModel;
    protected $userVerifyModel;
    protected $kkModel;
    protected $financeNotifyLogModel;

    public function __construct()
    {
        parent::__construct();

        $this->blsLib = new Bls();
        $this->yuqueLib = new Yuque();
        $this->alipayLib = new Alipay();

        $this->withdrawOrderModel = new FinanceWithdrawOrder();
        $this->userVerifyModel = new UserVerify();
        $this->kkModel = new FinanceKk();
        $this->financeNotifyLogModel = new FinanceNotifyLog();

    }

    /**
     * 获取用户提现支付宝信息
     * */
    public function getUserAlipay($userId){
        $code = Hint::SUCCESS;
        $msg = '';
        $data = [];

        do {
            if (empty($userId)) {
                $code = Hint::LOGIN_OUT;
                break;
            }

            $info = $this->withdrawOrderModel->getUserAlipay($userId, 0);
    
            $data['id'] = $info['id'];
            $data['user_id'] = $info['user_id'];
            $data['worker_name'] = $info['worker_name'];
            $data['idcard_no'] = $info['idcard_no'];
            $data['worker_account'] = $info['worker_account'];
            $data['bank_code'] = $info['bank_code'];
            $data['bank_source'] = $info['bank_source'];

        }while(false);

        return compact('code','msg','data');
    }

    /**
     * 用户提现支付宝保存
     * */
    public function saveUserAlipay($userId, $phone, $workerAccount, $bankCode=0, $bankSource=0){
        $code = Hint::SUCCESS;
        $msg = '';
        $data = [];

        do {
            if (empty($userId)) {
                $code = Hint::LOGIN_OUT;
                break;
            }
            $user_verify = $this->userVerifyModel->getInfoByUser(array('user_id'=>$userId ,'result_code'=>1000));
            if(empty($user_verify) || empty($user_verify['idcard_number'])){
                $code = Hint::USER_NOT_CERTIFICATION;
                break;
            }
            //删除旧的
            $this->withdrawOrderModel->financeYuqueDel($userId);
            //新的
            $log = [
                'user_id' => $userId,
                'worker_name' => $user_verify['idcard_name'],
                'receipt_channel' => 20,
                'worker_account' => $workerAccount,
                'worker_type' => 1,
                'idcard_no' => $user_verify['idcard_number'],
                'mobile_phone' => $phone,
                'bank_code' => $bankCode,
                'bank_source' => $bankSource,
            ];
            $this->withdrawOrderModel->financeYuqueAdd($log);

        }while(false);

        return compact('code','msg','data');
    }

    /**
     * 用户提现支付宝保存
     * */
    public function delUserAlipay($userId){
        $code = Hint::SUCCESS;
        $msg = '';
        $data = [];

        do {
            if (empty($userId)) {
                $code = Hint::LOGIN_OUT;
                break;
            }

            //删除旧的
            $this->withdrawOrderModel->financeYuqueDel($userId);

        }while(false);

        return compact('code','msg','data');
    }

    /**
     * 后台审核同意慧用工提现操作
     * */
    public function withdrawPayYuqueOrder($orderSn) {
        $code = Hint::SUCCESS;
        $msg = '';
        $data = [];
        do{
            if (empty($orderSn)) {
                $code = Hint::PARAM_ERROR;
                break;
            }
            if (!redis_lock('LOCK:payYuqueOrder:' . $orderSn, 10)) {
                $code = Hint::SAME_TIME_NOT_REPEAT;
                break;
            }

            // 查询订单
            $orderData = $this->withdrawOrderModel->get_order($orderSn);
            if(empty($orderData)){
                $code = Hint::PARAM_ERROR;
                $msg = '订单不存在';
                break;
            }

            // 校验订单是否处理过
            if($orderData['status'] != 0){
                $code = Hint::PARAM_ERROR;
                $msg = '订单已处理';
                break;
            }

            if($orderData['bank_id'] < 0){
                $code = Hint::BANK_NO_EXIST;
                break;
            }

            $user_verify = $this->userVerifyModel->getInfoByUser(array('user_id'=>$orderData['user_id'] ,'result_code'=>1000));
            if(empty($user_verify) || empty($user_verify['idcard_number'])){
                $code = Hint::USER_NOT_CERTIFICATION;
                break;
            }
            //查询支付宝
            $alipayInfo = $this->withdrawOrderModel->getUserAlipay($orderData['user_id'], $orderData['id']);
            if(empty($alipayInfo)) {
                $code = Hint::ALIPAY_NO_EXIST;
                break;
            }

            // 扣除费率后金额
            $taxAfter = $orderData['tax_after'];

            //测试环境提现都是1
            if (checkAppEnv()) {
                // $taxAfter = 100;
            }
            //查询余额
            $yuqueBalance = $this->yuqueLib->cooperatorBalance();
            $yuqueBalance = empty($yuqueBalance['data']['balance']) ? 0 : $yuqueBalance['data']['balance'];
            if($yuqueBalance < $taxAfter) {
                $code = Hint::FINANCE_MP_RMB_NOT_ENOUGH;
                $msg = '慧用工余额不足无法提现';
                break;
            }

            //请求
            $param = [
                'workerName' => $alipayInfo['worker_name'],
                'workerAccount' => $alipayInfo['worker_account'],
                'idNumber' => $alipayInfo['idcard_no'],
                'workerMobile' => $alipayInfo['mobile_phone'],
                'distributeAmount' => $taxAfter,//支付扣税后金额
                'requestNo' => $orderData['order_sn'],
            ];
            try {
                $yuqueRes = $this->yuqueLib->distributeSingleDistribute($param);
            } catch (Exception $e) {
                $code = Hint::ERR_SYS_FAIL;
                $msg = '服务异常:'.$e->getMessage();
                write_log('error_yuque', 'withdrawPayYuqueOrder 请求异常', ['param'=>$param, 'message'=>$e->getMessage(), 'line'=>$e->getLine()]);
                break;
            }

            DB::beginTransaction();
            try {
                if($yuqueRes['code'] != 0) {
                    $remark = $orderData['remark'].$yuqueRes['code'].' '.$yuqueRes['msg'];
                    if($yuqueRes['code'] == -1) {
                        //不退金币 手动处理
                        $remark = $remark.' | 不退金币,请联系开发';
                    }else{
                        //退金币
                        $config = config('pay');
                        $kk_desc = $config['wallet_change_desc']['kk_user_withdraw_fail'];
                        $kk_amount = intval($orderData['kk_amount']);
                        $this->kkModel->inc($orderData['user_id'], 0, 0, 5, $kk_amount, $kk_desc);
                    }
                    //更新订单状态为4：交易失败
                    $updateOrder = $this->withdrawOrderModel->pay_order(
                        $orderData['order_sn'],
                        '',
                        $orderData['tax_after'],
                        8,
                        0,
                        4,
                        '',
                        $remark
                    );
                }else{
                    //更新订单状态为3：进行中
                    $updateOrder = $this->withdrawOrderModel->pay_order(
                        $orderData['order_sn'],
                        $yuqueRes['data']['distributeId'],
                        $orderData['tax_after'],
                        8,
                        0,
                        3,
                        '',
                        ''
                    );
                }
                DB::commit();
            } catch (\Exception $e) {
                DB::rollBack();
    
                write_log('error_yuque', 'withdrawPayYuqueOrder 数据更新异常', ['param'=>$param, 'yuqueRes'=>$yuqueRes, 'message'=>$e->getMessage(), 'line'=>$e->getLine()]);
            }

        }while(false);

        return compact('code','msg','data');
    }

    /**
     * 提现回调 慧用工
     * */
    public function yuqueNotify($cooperatorId, $businessBody){
        $code = Hint::SUCCESS;
        $msg = '';
        $data = ['cooperatorId'=>$cooperatorId, 'businessBody'=>$businessBody];

        do {
            //解密
            $yuqueRes = $this->yuqueLib->strHuiYDecrypt($cooperatorId, $businessBody);
            if(empty($yuqueRes)) {
                $code = Hint::PARAM_ERROR;
                $msg = '解密失败';
                break;
            }
            $data['yuqueRes'] = $yuqueRes;
            write_log('yuque', 'yuqueNotify', $data);

            $orderSn = $yuqueRes['requestNo'];
            $distributeId = $yuqueRes['distributeId'];

            // 查询订单
            $orderData = $this->withdrawOrderModel->get_order($orderSn);
            if(empty($orderData)){
                $code = Hint::PARAM_ERROR;
                $msg = '订单不存在';
                break;
            }
            // 校验订单是否处理过
            if($orderData['status'] != 3){
                break;
            }
            // 是否是慧用工
            if($orderData['pay_type'] != 8){
                $code = Hint::PARAM_ERROR;
                $msg = '不是慧用工提现';
                break;
            }

            //60-打款成功，70-打款失败 90-已退票
            $state = 6;//6失败
            if($yuqueRes['distributeStatus'] == 60) {
                $state = 7;//7成功
            }

            //日志
            DB::beginTransaction();

            try{
                // 创建回调支付log
                $notifyLogId = $this->financeNotifyLogModel->create([
                    'user_id' => $orderData['user_id'],
                    'order_id' => $orderData['order_id'],
                    'trade_sn' => $distributeId,
                    'pay_amount' => $orderData['tax_after'],
                    'status' => $state,
                    'result' => json_encode($data,JSON_UNESCAPED_UNICODE),
                    'channel' => 'YUQUE',
                ]);
                //6失败
                if($state == 6) {
                    $remark = $orderData['remark'].$yuqueRes['distributeStatus'].' '.$yuqueRes['remark'];
                    $updateOrder = $this->withdrawOrderModel->payOrderStatus($orderData['order_id'], 3, 4, $distributeId, $remark);
                    //退钱
                    $config = config('pay');
                    $kk_desc = $config['wallet_change_desc']['kk_user_withdraw_fail'];
                    $this->kkModel->inc($orderData['user_id'], 0, 0, 5, (int)$orderData['kk_amount'], $kk_desc);
                }
                //7成功
                if($state == 7) {
                    $updateOrder = $this->withdrawOrderModel->payOrderStatus($orderData['order_id'], 3, 1, $distributeId);
                }

                DB::commit();
            } catch (Exception $e) {
                DB::rollBack();
                $code = Hint::ERR_SYS_FAIL;
                $data['error_msg'] = $e->getMessage();
                break;
            }

        }while(false);
        if($code != Hint::SUCCESS) {
            write_log('error_yuque', 'yuqueNotify '.$msg, $data);
        }

        return compact('code','msg','data');
    }

    /**
     * 后台审核同意支付宝提现操作
     * */
    public function withdrawPayAlipayOrder($orderSn) {
        $code = Hint::SUCCESS;
        $msg = '';
        $data = [];
        do{
            if (empty($orderSn)) {
                $code = Hint::PARAM_ERROR;
                break;
            }
            if (!redis_lock('LOCK:withdrawPayAlipayOrder:' . $orderSn, 10)) {
                $code = Hint::SAME_TIME_NOT_REPEAT;
                break;
            }

            // 查询订单
            $orderData = $this->withdrawOrderModel->get_order($orderSn);
            if(empty($orderData)){
                $code = Hint::PARAM_ERROR;
                $msg = '订单不存在';
                break;
            }

            // 校验订单是否处理过
            if($orderData['status'] != 0){
                $code = Hint::PARAM_ERROR;
                $msg = '订单已处理';
                break;
            }

            if($orderData['bank_id'] < 0){
                $code = Hint::BANK_NO_EXIST;
                break;
            }

            //实名认证
            $user_verify = $this->userVerifyModel->getInfoByUser(array('user_id'=>$orderData['user_id'] ,'result_code'=>1000));
            if(empty($user_verify) || empty($user_verify['idcard_number'])){
                $code = Hint::USER_NOT_CERTIFICATION;
                break;
            }
            //查询支付宝
            $alipayInfo = $this->withdrawOrderModel->getUserAlipay($orderData['user_id'], $orderData['id']);
            if(empty($alipayInfo)) {
                $code = Hint::ALIPAY_NO_EXIST;
                break;
            }

            // 扣除费率后金额
            $taxAfter = $orderData['tax_after'];

            //测试环境提现都是1角
            if (checkAppEnv()) {
                $taxAfter = 10;
            }

            //支付宝资金账户可用余额 分
            // $availableAmount = $this->alipayLib->accountQuery();
            // if($availableAmount < $taxAfter) {
            //     $upData = ['pay_type'=>8, 'remark'=>$orderData['remark'].'支付宝官方余额不足,申请慧用工提现|'];
            //     $upRes = $this->withdrawOrderModel->withdrawOrderUpdate($orderData['order_sn'], $upData);
            //     if($upData < 1) {
            //         $code = Hint::ALIPAY_NO_EXIST;
            //         $msg = '支付宝官方余额不足,申请慧用工提现,修改失败';
            //         break;
            //     }
            //     //支付宝慧用工提现申请
            //     $orderData['pay_type'] = $upData['pay_type'];
            //     $orderData['remark'] = $upData['remark'];
            //     $res = $this->_HandleWithdrawPayYuque($orderData, $taxAfter, $alipayInfo);
            //     $code = $res['code'];
            //     $msg = $res['msg'];
            //     $data = $res['data'];
            //     break;
            // }

            // //支付宝提现申请
            // $res = $this->_HandleWithdrawPayAlipay($orderData, $taxAfter, $alipayInfo);
            // if($res['data']['needChange'] == 1) {
            //     $orderData = $this->withdrawOrderModel->get_order($orderSn);
            //     $upData = ['pay_type'=>8, 'remark'=>$orderData['remark'].'支付宝提现失败,申请慧用工提现|'];
            //     $upRes = $this->withdrawOrderModel->withdrawOrderUpdate($orderData['order_sn'], $upData);
            //     if($upData < 1) {
            //         $code = Hint::ALIPAY_NO_EXIST;
            //         $msg = '支付宝提现失败,申请慧用工提现,修改失败';
            //         break;
            //     }
            //     //支付宝慧用工提现申请
            //     $orderData['pay_type'] = $upData['pay_type'];
            //     $orderData['remark'] = $upData['remark'];
            //     $res = $this->_HandleWithdrawPayYuque($orderData, $taxAfter, $alipayInfo);
            // }
            DB::beginTransaction();
            try{
                // 创建回调支付log
                $notifyLogId = $this->financeNotifyLogModel->create([
                    'user_id' => $orderData['user_id'],
                    'order_id' => $orderData['order_id'],
                    'trade_sn' => 0,
                    'pay_amount' => $orderData['tax_after'],
                    'status' => 7,//成功
                    'result' => json_encode($data,JSON_UNESCAPED_UNICODE),
                    'channel' => 'ALIPAY',
                ]);

                $updateOrder = $this->withdrawOrderModel->payOrderStatus($orderData['order_id'], 0, 1, 0);

                DB::commit();
            } catch (Exception $e) {
                DB::rollBack();
                $code = Hint::ERR_SYS_FAIL;
                $data['error_msg'] = $e->getMessage();
                break;
            }

        }while(false);

        return compact('code','msg','data');
    }


    /**
     * 支付宝慧用工提现申请
     * */
    public function _HandleWithdrawPayYuque($orderData, $taxAfter, $alipayInfo) {
        $code = Hint::SUCCESS;
        $msg = '';
        $data = [];
        do{
            //查询余额
            $yuqueBalance = $this->yuqueLib->cooperatorBalance();
            $yuqueBalance = empty($yuqueBalance['data']['balance']) ? 0 : $yuqueBalance['data']['balance'];
            //慧用工服务费
            $yuqueNeedNum = ceil($taxAfter*0.05);
            if($yuqueBalance < ($taxAfter+$yuqueNeedNum)) {
                $code = Hint::FINANCE_MP_RMB_NOT_ENOUGH;
                $msg = '慧用工余额不足无法提现';
                break;
            }

            //请求
            $param = [
                'workerName' => $alipayInfo['worker_name'],
                'workerAccount' => $alipayInfo['worker_account'],
                'idNumber' => $alipayInfo['idcard_no'],
                'workerMobile' => $alipayInfo['mobile_phone'],
                'distributeAmount' => $taxAfter,//支付扣税后金额
                'requestNo' => $orderData['order_sn'],
            ];
            try {
                $yuqueRes = $this->yuqueLib->distributeSingleDistribute($param);
            } catch (Exception $e) {
                $code = Hint::ERR_SYS_FAIL;
                $msg = '服务异常:'.$e->getMessage();
                write_log('error_yuque', 'withdrawPayYuqueOrder 请求异常', ['param'=>$param, 'message'=>$e->getMessage(), 'line'=>$e->getLine()]);
                break;
            }

            DB::beginTransaction();
            try {
                if($yuqueRes['code'] != 0) {
                    $remark = $orderData['remark'].$yuqueRes['code'].':'.$yuqueRes['msg'].'|';
                    if($yuqueRes['code'] == -1) {
                        //不退金币 手动处理
                        $remark = $remark.'不退金币,请联系开发|';
                    }else{
                        //退金币
                        $config = config('pay');
                        $kk_desc = $config['wallet_change_desc']['kk_user_withdraw_fail'];
                        $kk_amount = intval($orderData['kk_amount']);
                        $this->kkModel->inc($orderData['user_id'], 0, 0, 5, $kk_amount, $kk_desc);
                    }
                    //更新订单状态为4：交易失败
                    $updateOrder = $this->withdrawOrderModel->pay_order(
                        $orderData['order_sn'],
                        '',
                        $taxAfter,
                        8,
                        0,
                        4,
                        '',
                        $remark
                    );
                }else{
                    //更新订单状态为3：进行中
                    $updateOrder = $this->withdrawOrderModel->pay_order(
                        $orderData['order_sn'],
                        $yuqueRes['data']['distributeId'],
                        $taxAfter,
                        8,
                        0,
                        3,
                        '',
                        ''
                    );
                }
                DB::commit();
            } catch (\Exception $e) {
                DB::rollBack();

                write_log('error_yuque', 'withdrawPayYuqueOrder 数据更新异常', ['param'=>$param, 'yuqueRes'=>$yuqueRes, 'message'=>$e->getMessage(), 'line'=>$e->getLine()]);
            }

        }while(false);

        return compact('code','msg','data');
    }

    /**
     * 支付宝提现申请
     * */
    public function _HandleWithdrawPayAlipay($orderData, $taxAfter, $alipayInfo) {
        $code = Hint::SUCCESS;
        $msg = '';
        $data = [
            //是否需要换提现渠道 0=不需要 1=需要
            'needChange' => 1
        ];
        do{
            //请求
            $alipayRes = $this->alipayLib->transUniTransfer($orderData['order_sn'], $taxAfter/100, $alipayInfo['worker_account'], $alipayInfo['worker_name']);

            DB::beginTransaction();
            try {
                if($alipayRes['code'] != 1) {
                    //备注
                    $remark = $orderData['remark'].$alipayRes['code'].':'.$alipayRes['msg'].'|';
                    $needFalse = 1;
                    //系统异常
                    if($alipayRes['code'] == -1) {
                        $remark = $remark.'不退金币,请联系开发|';
                        $data['needChange'] = 0;
                    }
                    //系统繁忙
                    if(isset($alipayRes['sub_code']) && $alipayRes['sub_code']=='SYSTEM_ERROR') {
                        //不退金币 手动处理
                        $remark = $remark.'不退金币,请联系开发|';
                        $data['needChange'] = 0;
                    }

                    if($data['needChange'] == 0) {
                        //更新订单状态为4：交易失败
                        $updateOrder = $this->withdrawOrderModel->pay_order(
                            $orderData['order_sn'],
                            '',
                            $taxAfter,
                            9,
                            0,
                            4,
                            '',
                            $remark
                        );
                    }
                }else{
                    //更新订单状态为3：进行中
                    $updateOrder = $this->withdrawOrderModel->pay_order(
                        $orderData['order_sn'],
                        $alipayRes['data']['order_id'],
                        $taxAfter,
                        9,
                        0,
                        3,
                        '',
                        ''
                    );
                    $data['needChange'] = 0;
                }
                DB::commit();
            } catch (\Exception $e) {
                DB::rollBack();
    
                write_log('error_yuque', 'withdrawPayAlipayOrder 数据更新异常', ['orderData'=>$orderData, 'alipayRes'=>$alipayRes, 'message'=>$e->getMessage(), 'line'=>$e->getLine()]);
            }

        }while(false);

        return compact('code','msg','data');
    }

    /**
     * 提现回调 支付宝
     * */
    public function alipayNotify($params){
        $code = Hint::SUCCESS;
        $msg = '';
        $data = [];

        do {
            //支付宝转账业务单据查询
            $alipayRes = $this->alipayLib->transCommonQuery($params['out_biz_no']);
            if($alipayRes['code'] != 1) {
                $code = Hint::ERROR;
                $msg = $alipayRes['msg'];
            }
            $alipayRes = $alipayRes['data'];
            $orderSn = $alipayRes['out_biz_no'];
            $outTradeSn = $alipayRes['order_id'];

            //订单数据获取
            $orderData = $this->withdrawOrderModel->get_order($orderSn);

            if(empty($orderData)){
                $code = Hint::PARAM_ERROR;
                $msg = '订单不存在';
                break;
            }
            // 校验订单是否处理过
            if($orderData['status'] != 3){
                break;
            }
            // 是否是支付宝
            if($orderData['pay_type'] != 9){
                $code = Hint::PARAM_ERROR;
                $msg = '不是支付宝提现';
                break;
            }

            //失败
            if($alipayRes['status'] == 'FAIL') {
                //日志
                DB::beginTransaction();
                try{
                    // 创建回调支付log
                    $notifyLogId = $this->financeNotifyLogModel->create([
                        'user_id' => $orderData['user_id'],
                        'order_id' => $orderData['order_id'],
                        'trade_sn' => $outTradeSn,
                        'pay_amount' => $orderData['tax_after'],
                        'status' => 6,//失败
                        'result' => json_encode($data,JSON_UNESCAPED_UNICODE),
                        'channel' => 'ALIPAY',
                    ]);

                    $remark = $orderData['remark'].'支付宝 FAIL|';

                    $updateOrder = $this->withdrawOrderModel->payOrderStatus($orderData['order_id'], 3, 4, '', $remark);
                    //退钱
                    $config = config('pay');
                    $kk_desc = $config['wallet_change_desc']['kk_user_withdraw_fail'];
                    $this->kkModel->inc($orderData['user_id'], 0, 0, 5, (int)$orderData['kk_amount'], $kk_desc);

                    DB::commit();
                } catch (Exception $e) {
                    DB::rollBack();
                    $code = Hint::ERR_SYS_FAIL;
                    $data['error_msg'] = $e->getMessage();
                    break;
                }
            }
            //成功
            if($alipayRes['status'] == 'SUCCESS') {
                //日志
                DB::beginTransaction();
                try{
                    // 创建回调支付log
                    $notifyLogId = $this->financeNotifyLogModel->create([
                        'user_id' => $orderData['user_id'],
                        'order_id' => $orderData['order_id'],
                        'trade_sn' => $outTradeSn,
                        'pay_amount' => $orderData['tax_after'],
                        'status' => 7,//成功
                        'result' => json_encode($data,JSON_UNESCAPED_UNICODE),
                        'channel' => 'ALIPAY',
                    ]);

                    $updateOrder = $this->withdrawOrderModel->payOrderStatus($orderData['order_id'], 3, 1, $alipayRes['pay_fund_order_id']);

                    DB::commit();
                } catch (Exception $e) {
                    DB::rollBack();
                    $code = Hint::ERR_SYS_FAIL;
                    $data['error_msg'] = $e->getMessage();
                    break;
                }
            }

        }while(false);
        if($code != Hint::SUCCESS) {
            write_log('error_alipay', 'alipayNotify 处理失败'.$msg, $data);
        }

        return compact('code','msg','data');
    }


}
